package pl.edu.pw.tm.zestawfiltrow;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Locale;

import javax.imageio.ImageIO;
import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.MatteBorder;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import pl.edu.pw.tm.zestawfiltrow.panels.FiltersPanel;
import pl.edu.pw.tm.zestawfiltrow.panels.ImagePanel;
import pl.edu.pw.tm.zestawfiltrow.utils.zestawFiltrow;
 
public class FiltryCyfrowe {
	private static Logger log = Logger.getLogger(FiltryCyfrowe.class);
	private JFrame frame;
	
	private JMenuItem openFileMenu;
	private JMenuItem saveAsFileMenu;
	private JMenuItem closeWindowMenu;
	private JMenu menuOkno; 
	private JMenu menyZmienStyl;
	private JPanel filterPanel;
	private ImagePanel imagePanel;
	private JButton btnZamknij;
	private JButton btnWczytajZdjecie;
	private JButton btnZapiszZdjecie;
	
	private File choosenImageFile;
//	private BufferedImage image;
	
	public static void main(String[] args) {
		PropertyConfigurator.configure("log4j.properties");

		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					FiltryCyfrowe window = new FiltryCyfrowe();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public FiltryCyfrowe() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setTitle(zestawFiltrow.frameTitle);
		frame.setSize(zestawFiltrow.frameWidth, zestawFiltrow.frameHeight);
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		frame.setResizable(false);
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				int result = JOptionPane.showConfirmDialog(frame, "Zamknąć program?", "Zamknąć?", JOptionPane.YES_NO_OPTION,  JOptionPane.QUESTION_MESSAGE);
				if(result == JOptionPane.YES_OPTION) {
					frame.dispose();
				}
			}
			
		});
		frame.setLocale(new Locale("pl", "PL"));
		ustawStyl();

		final JFileChooser chooser = new JFileChooser();
		FileNameExtensionFilter jpgFilter = new FileNameExtensionFilter("Pliki obrazów (jpg, bmp)", "jpg", "jpeg", "bmp");
		chooser.setFileFilter(jpgFilter);
		chooser.addChoosableFileFilter(jpgFilter);
		
		chooser.setAcceptAllFileFilterUsed(true);
		chooser.setMultiSelectionEnabled(false);

		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		JMenu menuPlik = new JMenu("Plik");
		menuBar.add(menuPlik);

		openFileMenu = new JMenuItem("Otwórz plik");
		openFileMenu.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int result = chooser.showOpenDialog(frame);
				if (result == JFileChooser.APPROVE_OPTION) {
					log.info("Wybrano: " + chooser.getSelectedFile());
					choosenImageFile = chooser.getSelectedFile();

					saveAsFileMenu.setEnabled(true);
					btnZapiszZdjecie.setEnabled(true);
					
					BufferedImage image = null;
					try {
						image = ImageIO.read(choosenImageFile);
					} catch (IOException ex) {
						ex.printStackTrace();
					}
					
					imagePanel.setClearImage(image);
				}
			}
		});
		openFileMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
		menuPlik.add(openFileMenu);
		menuPlik.addSeparator();

		saveAsFileMenu = new JMenuItem("Zapisz jako");
		saveAsFileMenu.setEnabled(false);
		saveAsFileMenu.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int result = chooser.showSaveDialog(frame);
				if(result == JFileChooser.APPROVE_OPTION) {
					choosenImageFile = chooser.getSelectedFile();				
				}
				
				if(choosenImageFile != null) {
					try {
						String path = choosenImageFile.getCanonicalPath();
						log.info("Zapisuje do: " + path);
						File newImage  = new File(path);
						ImageIO.write(imagePanel.getFilteredImage(), path.substring(path.lastIndexOf(".")), newImage);
					} catch (IOException e1) {
						e1.printStackTrace();
					}					
				}
			}
		});
		saveAsFileMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK));
		menuPlik.add(saveAsFileMenu);

		menuPlik.addSeparator();
		
		closeWindowMenu = new JMenuItem("Zakończ");
		closeWindowMenu.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int result = JOptionPane.showConfirmDialog(frame, "Zamknąć program?", "Zamknąć?", JOptionPane.YES_NO_OPTION,  JOptionPane.QUESTION_MESSAGE);
				
				if(result == JOptionPane.OK_OPTION) {
					frame.dispose();
				}
			}
		});
		closeWindowMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
		menuPlik.add(closeWindowMenu);
		
		menuOkno = new JMenu("Okno");
		menuBar.add(menuOkno);
		
		menyZmienStyl = new JMenu("Zmień styl");
		menuOkno.add(menyZmienStyl);
		
		imagePanel = new ImagePanel();
		imagePanel.setBackground(Color.WHITE);
		imagePanel.setBorder(new MatteBorder(6, 1, 1, 1, (Color) new Color(0, 0, 0)));
		
		filterPanel = new FiltersPanel(frame, imagePanel);
		filterPanel.setBorder(new TitledBorder(null, "Filtry", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		btnZamknij = new JButton("Zamknij");
		btnZamknij.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				int result = JOptionPane.showConfirmDialog(frame, "Zamknąć program?", "Zamknąć?", JOptionPane.YES_NO_OPTION,  JOptionPane.QUESTION_MESSAGE);
				
				if(result == JOptionPane.OK_OPTION) {
					frame.dispose();
				}
			}
		});
		
		btnWczytajZdjecie = new JButton("Wczytaj zdjęcie");
		btnWczytajZdjecie.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int result = chooser.showOpenDialog(frame);
				if (result == JFileChooser.APPROVE_OPTION) {
					log.info("Wybrano: " + chooser.getSelectedFile());
					choosenImageFile = chooser.getSelectedFile();

					saveAsFileMenu.setEnabled(true);
					btnZapiszZdjecie.setEnabled(true);
					BufferedImage image = null;
					try {
						image = ImageIO.read(choosenImageFile);
					} catch (IOException ex) {
						ex.printStackTrace();
					}
					
					imagePanel.setClearImage(image);
				}

			}
		});

		btnZapiszZdjecie = new JButton("Zapisz zdjęcie");
		btnZapiszZdjecie.setEnabled(false);
		btnZapiszZdjecie.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
					int result = chooser.showSaveDialog(frame);
					File newChoosenImageFile = null;
					if(result == JFileChooser.APPROVE_OPTION) {
						newChoosenImageFile = chooser.getSelectedFile();				
					}
				
				if(newChoosenImageFile != null) {
					try {
						String path = newChoosenImageFile.getCanonicalPath();
						log.info("Zapisuje do: " + path);
						File newImage  = new File(path);
						ImageIO.write(imagePanel.getFilteredImage(), path.substring(path.lastIndexOf(".")+1), newImage);
						
					} catch (IOException e1) {
						e1.printStackTrace();
					}					
				}
			}
		});
		GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.TRAILING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addComponent(imagePanel, 570, 570, 570)
					.addGap(19)
					.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
						.addGroup(groupLayout.createSequentialGroup()
							.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false)
								.addComponent(btnZamknij, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
								.addComponent(btnZapiszZdjecie, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
								.addComponent(btnWczytajZdjecie, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
							.addGap(40))
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(filterPanel, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE)
							.addContainerGap())))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING, false)
						.addGroup(groupLayout.createSequentialGroup()
							.addComponent(filterPanel, GroupLayout.PREFERRED_SIZE, 300, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
							.addComponent(btnWczytajZdjecie)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(btnZapiszZdjecie)
							.addGap(18)
							.addComponent(btnZamknij))
						.addComponent(imagePanel, Alignment.TRAILING, 570, 570, 570))
					.addContainerGap())
		);
		imagePanel.setLayout(new BorderLayout(0, 0));
		frame.getContentPane().setLayout(groupLayout);
		
		ButtonGroup styleGroup = new ButtonGroup();
		JRadioButtonMenuItem styleRadioMenu;
		for (final LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
			if ("Nimbus".equals(info.getName()) || "GTK+".equals(info.getName()) || "Windows".equals(info.getName()) ) {
				styleRadioMenu = new JRadioButtonMenuItem(info.getName());
				styleRadioMenu.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e) {
						ustawStyl(info.getClassName());
						chooser.updateUI();
					}
				});
				if(info.getClassName().equals(getLookAndFeelStyle()))
					styleRadioMenu.setSelected(true);
				else
					styleRadioMenu.setSelected(false);
				styleGroup.add(styleRadioMenu);
				menyZmienStyl.add(styleRadioMenu);
			}
		}
		
		

	}


	private void ustawStyl() {
		ustawStyl(getLookAndFeelStyle());
	}
	
	private void ustawStyl(String name) {
		try {
			UIManager.setLookAndFeel(name);
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		SwingUtilities.updateComponentTreeUI(frame);
	}

	private String getLookAndFeelStyle() {
		String windowsStyle = null;
		String gtkStyle = null;
		String nimbusStyle = null;

		for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
			if ("Nimbus".equals(info.getName()))
				nimbusStyle = info.getClassName();
			else if ("GTK+".equals(info.getName()))
				gtkStyle = info.getClassName();
			else if ("Windows".equals(info.getName()))
				windowsStyle = info.getClassName();
		}

		if (gtkStyle != null)
			return gtkStyle;
		else if (windowsStyle != null)
			return windowsStyle;
		else if (nimbusStyle != null)
			return nimbusStyle;

		return UIManager.getCrossPlatformLookAndFeelClassName();
	}
}
